﻿using System;

public class Well512
{
	private uint[] state = new uint[16];
	private uint i = 0;

	public static Well512 Instance { get; private set; }

	private Well512(int seed)
	{
		Init((uint)seed);
	}

	private void Init(uint seed)
	{
		for (uint i = 0; i < 16; i++)
			state[i] = ((seed * i) << 8) & 0xda442d24;
	}

	public static Well512 Create(int seed)
	{
		return new Well512(seed);
	}

	public static Well512 CreateStatic(int seed)
	{
		Instance = new Well512(seed);

		return Instance;
	}

	private uint Next()
	{
		uint a, b, c, d;

		a = state[i];
		c = state[(i + 13) & 15];
		b = a ^ c ^ (a << 16) ^ (c << 15);
		c = state[(i + 9) & 15];
		c = c ^ (c >> 11);
		a = state[i] = b ^ c;
		d = a ^ ((a << 5) & 0xda442d24);
		i = (i + 15) & 15;
		a = state[i];
		state[i] = a ^ b ^ d ^ (a << 2) ^ (b << 18) ^ (c << 28);

		return state[i];
	}

	public int NextInt()
	{
		return NextInt(int.MaxValue);
	}

	public int NextInt(int max)
	{
		return (int)(Next() % max);
	}

	public int NextInt(int min, int max)
	{
		return NextInt(max - min) + min;
	}

	public float NextFloat()
	{
		return NextInt(100) * 0.01f;
	}
}
